﻿/**************************************************************************
创建时间:	2020/5/13 10:05:32    
作	  者:	张存
邮 	  箱:	zhangcunliang@126.com

描	述：
记	录：
    2020.9.15 解决当对象属性不包含已设置的dmc映射时报错的bug
***************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using ZhCun.Utils.Helpers;

namespace ZhCun.Win.Extend
{
    /// <summary>
    /// 数据 与 控件映射扩展组件
    /// Data Control Mapping
    /// </summary>
    [ProvideProperty("IsUse", typeof(Control))]
    [ProvideProperty("EnterIsTab", typeof(Control))]
    [ProvideProperty("ValueMember", typeof(Control))]
    [ProvideProperty("DisplayMember", typeof(Control))]
    [ProvideProperty("TabIndex", typeof(Control))]
    public class DCM : Component, IExtenderProvider
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public DCM(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
        }
        /// <summary>
        /// 是否能被扩展的控件
        /// </summary>
        /// <param name="extendee">扩展对象</param>
        /// <returns>能被扩展返回true</returns>
        public bool CanExtend(object extendee)
        {
            return extendee is IEditDCM;
            //return
            //    extendee is EditText ||
            //    extendee is EditDateTimePicker ||
            //    extendee is EditComboBox ||
            //    extendee is EditCheckBox;
        }

        #region 系统生成

        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private IContainer components = null;
        /// <summary> 
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            components = new Container();
        }

        #endregion

        #region 配置实体

        /// <summary>
        /// 输出参数绑定的参数对象
        /// </summary>
        public class SetupModel
        {
            /// <summary>
            /// 是否启用
            /// </summary>
            public bool IsUse { set; get; }
            /// <summary>
            /// 要绑定的控件
            /// </summary>
            public IEditDCM BindControl { set; get; }
            /// <summary>
            /// 值 对应属性（字段）名
            /// </summary>
            public string ValueMember { set; get; }
            /// <summary>
            /// 显示 对应属性（字段）名
            /// </summary>
            public string DisplayMember { set; get; }
            /// <summary>
            /// 回车响应 tab 按键，默认为true
            /// </summary>
            public bool EnterIsTab { get; set; } = true;
            /// <summary>
            /// 控件的TabIndex
            /// </summary>
            public int TabIndex { set; get; }
        }

        #endregion

        #region 对象与控件交互操作

        /// <summary>
        /// 所有文本框的验证信息字典
        /// </summary>
        private Dictionary<IEditDCM, SetupModel> ControlDict = new Dictionary<IEditDCM, SetupModel>();

        /// <summary>
        /// 获取指定控件的设置model，如果不存在则新增
        /// </summary>
        public SetupModel GetSetupModel(Control control)
        {
            IEditDCM editControl = control as IEditDCM;
            if (!ControlDict.ContainsKey(editControl))
            {
                var m = new SetupModel
                {
                    BindControl = editControl,
                    IsUse = true,
                    EnterIsTab = true,
                    ValueMember = string.Empty,
                    DisplayMember = string.Empty
                };

                ControlDict[editControl] = m;
                RegisterKeyDownEvent(control);
                //SetBindControl(m);
            }
            return ControlDict[editControl];
        }
        /// <summary>
        /// 注册文本框的事件
        /// </summary>
        void RegisterKeyDownEvent(Control control)
        {
            //var control = edit as Control;
            control.KeyDown -= Control_KeyDown;
            control.KeyDown += Control_KeyDown;
        }
        /// <summary>
        /// 响应按键事件
        /// </summary>
        private void Control_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                IEditDCM ctr = sender as IEditDCM;
                if (ControlDict.ContainsKey(ctr))
                {
                    var arg = ControlDict[ctr];
                    if (arg.EnterIsTab && ctr is Control c)
                    {
                        c.Focus();
                        SendKeys.Send("{Tab}");
                    }
                }
            }
        }
        /// <summary>
        /// 获取DataRow对象，DataRow 不能为空
        /// </summary>
        public void GetDataRowByControl(ref DataRow dr)
        {
            if (dr == null) return;
            DataTable dt = dr.Table;
            foreach (var item in ControlDict)
            {
                if (!item.Value.IsUse) continue;

                if (!dt.Columns.Contains(item.Value.DisplayMember) && dt.Columns.Contains(item.Value.ValueMember))
                {
                    continue;
                }

                if (!item.Value.DisplayMember.IsEmpty() && item.Key.IsDisplayChanged)
                {
                    dr[item.Value.DisplayMember] = item.Key.DisplayItem;
                }

                if (!item.Value.ValueMember.IsEmpty() && item.Key.IsValueChanged)
                {
                    dr[item.Value.ValueMember] = item.Key.ValueItem;
                }
            }
        }
        /// <summary>
        /// 根据DataRow设置控件的值
        /// </summary>
        public void SetDataRowToControl(DataRow dr)
        {
            if (dr == null) return;
            foreach (var item in ControlDict)
            {
                if (!item.Value.IsUse) continue;

                if (!item.Value.DisplayMember.IsEmpty())
                {
                    var val = dr[item.Value.DisplayMember];
                    if (val != null && val != DBNull.Value)
                    {
                        item.Key.DisplayItem = val;
                    }
                }

                if (!item.Value.ValueMember.IsEmpty())
                {
                    var val = dr[item.Value.ValueMember];
                    if (val != null && val != DBNull.Value)
                    {
                        item.Key.ValueItem = val;
                    }
                }
            }
        }
        /// <summary>
        /// 根据控件映射，输出为字典对象
        /// </summary>
        public Dictionary<string, object> GetDictionaryByControl()
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            foreach (var item in ControlDict)
            {
                if (!item.Value.IsUse) continue;

                if (!item.Value.ValueMember.IsEmpty())
                {
                    dict[item.Value.ValueMember] = item.Key.ValueItem;
                }

                if (!item.Value.DisplayMember.IsEmpty())
                {
                    dict[item.Value.DisplayMember] = item.Key.DisplayItem;
                }
            }

            return dict;
        }
        /// <summary>
        /// 根据字典对象，设置控件
        /// </summary>
        public void SetControlByDictionary(Dictionary<string, object> dict)
        {
            if (dict == null) return;
            foreach (var item in ControlDict)
            {
                if (!ControlDict[item.Key].IsUse) continue;

                if (!item.Value.ValueMember.IsEmpty())
                {
                    if (dict.ContainsKey(item.Value.ValueMember))
                    {
                        item.Key.ValueItem = dict[item.Value.ValueMember];
                    }
                }
                if (!item.Value.DisplayMember.IsEmpty())
                {
                    if (dict.ContainsKey(item.Value.DisplayMember))
                    {
                        item.Key.DisplayItem = dict[item.Value.DisplayMember];
                    }
                }
            }
        }
        /// <summary>
        /// 将控件值赋值到一个实体对象,modelObject 为空 直接 return
        /// </summary>
        public void GetObjectByControl(object modelObject)
        {
            if (modelObject == null) return;

            var dict = GetDictionaryByControl();

            ReflectionHelper.SetPropertyValue(modelObject, dict);

            foreach (var item in dict)
            {
                if (item.Value == null)
                {
                    ReflectionHelper.SetPropertyDefaultValue(modelObject, item.Key);
                }
            }
        }
        /// <summary>
        /// 根据对象值设置控件值
        /// </summary>
        public void SetObjectToControl(object obj)
        {
            if (obj is DataRow dr)
            {
                SetDataRowToControl(dr);
                return;
            }

            var dict = ReflectionHelper.GetPropertyNameAndValue(obj);

            SetControlByDictionary(dict);
        }
        /// <summary>
        /// 设置所有控件的 Text=Empty, tag=null
        /// </summary>
        public void SetControlValueEmpty()
        {
            foreach (var item in ControlDict)
            {
                if (!item.Value.IsUse) continue;

                item.Key.SetDefault();
            }
        }
        /// <summary>
        /// 根据绑定的列名获取控件对象，可用于验证后焦点获取
        /// </summary>
        public IEditDCM GetEdit(string colName)
        {
            foreach (var item in ControlDict)
            {
                if (item.Value.DisplayMember.StringEquals(colName) ||
                    item.Value.ValueMember.StringEquals(colName))
                {
                    return item.Key;
                }
            }

            return null;
        }
        /// <summary>
        /// 获取控件的Text属性值
        /// </summary>
        public string GetDisplayItem(string pName)
        {
            var c = GetEdit(pName);
            return c?.DisplayItem?.ToString();
        }
        /// <summary>
        /// 获取控件的Tag值
        /// </summary>
        public object GetValueItem(string pName)
        {
            var c = GetEdit(pName);
            return c?.ValueItem;
        }
        /// <summary>
        /// 根据绑定的属性名，获取控件，并获得焦点
        /// </summary>
        public void SetControlFocus(string pName)
        {
            var c = GetEdit(pName) as Control;

            if (c is TextBox txt)
            {
                txt.SelectAll();
            }
            c?.Focus();
        }

        #endregion

        #region 扩展到控件的属性

        /// <summary>
        /// 是否启用控件映射
        /// </summary>
        [Category("DataBind")]
        [Description("是否启用控件映射")]
        public bool GetIsUse(Control t)
        {
            SetupModel vInfo = GetSetupModel(t);
            return vInfo.IsUse;
        }
        /// <summary>
        /// 设置是否启用
        /// </summary>
        /// <param name="t">控件</param>
        /// <param name="s">是否启用</param>
        [Category("DataBind")]
        [Description("是否启用控件映射")]
        public void SetIsUse(Control t, bool s)
        {
            SetupModel vInfo = GetSetupModel(t);
            vInfo.IsUse = s;
        }
        /// <summary>
        /// 获取控件text值
        /// </summary>
        [Category("DataBind")]
        [Description("控件的显示值")]
        public string GetDisplayMember(Control t)
        {
            SetupModel vInfo = GetSetupModel(t);
            return vInfo.DisplayMember;
        }
        /// <summary>
        /// 设置控件text值
        /// </summary>
        [Category("DataBind")]
        [Description("控件的显示值")]
        public void SetDisplayMember(Control t, string s)
        {
            SetupModel vInfo = GetSetupModel(t);
            vInfo.DisplayMember = s;
        }
        /// <summary>
        /// 获取控件tag值
        /// </summary>
        [Category("DataBind")]
        [Description("获取控件存储值")]
        public string GetValueMember(Control t)
        {
            SetupModel vInfo = GetSetupModel(t);
            return vInfo.ValueMember;
        }
        [Category("DataBind")]
        [Description("获取控件存储值")]
        /// <summary>
        /// 设置控件tag值
        /// </summary>
        /// <param name="t"></param>
        /// <param name="s"></param>
        public void SetValueMember(Control t, string s)
        {
            SetupModel vInfo = GetSetupModel(t);
            vInfo.ValueMember = s;
        }
        /// <summary>
        /// 回车是否执行Tab按键
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        [Category("DataBind")]
        [Description("回车执行Tab按键")]
        public bool GetEnterIsTab(Control t)
        {
            SetupModel vInfo = GetSetupModel(t);
            return vInfo.EnterIsTab;
        }
        [Category("DataBind")]
        [Description("回车执行Tab按键")]
        /// <summary>
        /// 回车是否执行Tab按键
        /// </summary>
        public void SetEnterIsTab(Control t, bool yes)
        {
            SetupModel vInfo = GetSetupModel(t);
            //RegisterKeyDownEvent(t, yes);
            vInfo.EnterIsTab = yes;
        }

        /// <summary>
        /// 获取 tab 顺序
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        [Category("DCM")]
        [Description("设置控件TabIndex")]
        public int GetTabIndex(Control t)
        {
            SetupModel vInfo = GetSetupModel(t);
            return vInfo.TabIndex;
        }
        /// <summary>
        /// 设置 tab 顺序
        /// </summary>
        public void SetTabIndex(Control t, int index)
        {
            SetupModel vInfo = GetSetupModel(t);
            vInfo.TabIndex = index;
            t.TabIndex = index;
        }

        #endregion

        #region 注册 复制粘贴快捷键

        static Dictionary<string, object> CopyObject;

        bool IsRegisterCopy = false;

        /// <summary>
        /// 注册复制粘贴快捷键
        /// </summary>
        public void RegisterCopyKey(Form form)
        {
            if (IsRegisterCopy) return;
            IsRegisterCopy = true;
            if (form != null)
            {
                form.KeyDown -= Form_KeyDown;
                form.KeyDown += Form_KeyDown;
            }
        }

        private void Form_KeyDown(object sender, KeyEventArgs e)
        {
            if (Control.ModifierKeys == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.C)
            {
                CopyObject = GetDictionaryByControl();
                if (sender is FrmBase frm)
                {
                    frm.ShowMessage("已复制");
                }
                return;
            }
            if (Control.ModifierKeys == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.V)
            {
                SetControlByDictionary(CopyObject);
                CopyObject?.Clear();
                CopyObject = null;
                return;
            }
        }

        #endregion

    }
}
